package xyz.labmem.app.unit

import javafx.beans.property.SimpleBooleanProperty
import javafx.event.EventHandler
import javafx.geometry.Insets
import javafx.geometry.Pos
import javafx.scene.effect.DropShadow
import javafx.scene.layout.AnchorPane
import javafx.scene.layout.StackPane
import javafx.scene.paint.Color
import javafx.scene.shape.Polygon
import javafx.scene.text.Font
import javafx.scene.text.Text
import xyz.labmem.app.config.AppConfig
import xyz.labmem.app.util.mouseClickedPoll

class SwitchUnit(
    value: Boolean = false,
    private val trueText: String = "ON",
    private val falseText: String = "OFF",
    private val multiple: Int = 1
) : StackPane() {

    val valueProperty = SimpleBooleanProperty(value)

    private val enteredProperty = SimpleBooleanProperty(false)

    private val dropShadow = DropShadow()

    init {
        prefHeight = 30.0 * multiple
        prefWidth = 100.0 * multiple
        dropShadow.radius = 3.0 * multiple
        dropShadow.spread = 2.0 * multiple
        dropShadow.color = Color.WHITE
        val bkg1 = Polygon().apply {
            fill = Color.web("#FFFFFF")
            points.setAll(
                .0, .0,
                prefWidth - 3* multiple, .0,
                prefWidth, prefHeight,
                3.0* multiple, prefHeight,
            )
        }
        val bkg2 = Polygon().apply {
            fill = Color.web("#000000")
            points.setAll(
                2.0* multiple, 2.0* multiple,
                prefWidth - 5* multiple, 2.0* multiple,
                prefWidth - 2* multiple, prefHeight - 2* multiple,
                5.0* multiple, prefHeight - 2* multiple,
            )
        }
        children.add(AnchorPane(bkg1))
        children.add(AnchorPane(bkg2))
        val truePick = makeTruePick()
        val falsePick = makeFalsePick()
        children.add(truePick)
        children.add(falsePick)
        truePick.isVisible = value
        falsePick.isVisible = !value
        valueProperty.addListener { _, _, v ->
            truePick.isVisible = v
            falsePick.isVisible = !v
        }
        onMouseEntered = EventHandler {
            enteredProperty.value = true
        }
        onMouseExited = EventHandler {
            enteredProperty.value = false
        }
        onMouseClicked = mouseClickedPoll {
            valueProperty.value = !valueProperty.value
        }
    }

    private fun makeTruePick(): StackPane {
        val pane = StackPane()
        val lines = listOf(
            4.0* multiple, 0.0,
            this@SwitchUnit.prefWidth - 20* multiple, 0.0,
            this@SwitchUnit.prefWidth - 15* multiple, this@SwitchUnit.prefHeight - 5* multiple,
            10.0* multiple, this@SwitchUnit.prefHeight,
        )
        val lines1 = listOf(
            0.0, 0.0,
            this@SwitchUnit.prefWidth - 45* multiple, 0.0,
            this@SwitchUnit.prefWidth - 40* multiple, this@SwitchUnit.prefHeight - 5* multiple,
            3.0* multiple, this@SwitchUnit.prefHeight,
        )
        val pick = Polygon().apply {
            fill = Color.web("#FFFFFF")
            points.setAll(lines)
        }
        val tt = Text(trueText).apply {
            fill = Color.BLACK
            font = Font.loadFont(AppConfig.font, 30.0* multiple)
            rotate = -10.0
            effect = dropShadow
            setAlignment(this, Pos.TOP_LEFT)
            setMargin(this, Insets(-3.0* multiple, 0.0, 2.0* multiple, 5.0* multiple))
        }
        val ft = Text(falseText).apply {
            fill = Color.WHITE
            font = Font.loadFont(AppConfig.font, 20.0* multiple)
            rotate = 5.0
            setAlignment(this, Pos.BOTTOM_RIGHT)
            setMargin(this, Insets(0.0, 4.0* multiple, 5.0* multiple, .0))
            isVisible = false
        }
        pane.children.addAll(AnchorPane(pick), tt, ft)
        pane.prefWidth = prefWidth
        pane.prefHeight = prefHeight
        enteredProperty.addListener { _, _, v ->
            if (v) {
                ft.isVisible = true
                pick.points.setAll(lines1)
            } else {
                ft.isVisible = false
                pick.points.setAll(lines)
            }
        }
        return pane
    }

    private fun makeFalsePick(): StackPane {
        val pane = StackPane()
        val lines = listOf(
            20.0* multiple, 0.0,
            this@SwitchUnit.prefWidth, 4.0* multiple,
            this@SwitchUnit.prefWidth - 4* multiple, this@SwitchUnit.prefHeight,
            18.0* multiple, this@SwitchUnit.prefHeight,
        )
        val lines1 = listOf(
            40.0* multiple, 0.0,
            this@SwitchUnit.prefWidth, 4.0* multiple,
            this@SwitchUnit.prefWidth, this@SwitchUnit.prefHeight,
            38.0* multiple, this@SwitchUnit.prefHeight,
        )
        val pick = Polygon().apply {
            fill = Color.web("#FFFFFF")
            points.setAll(lines)
        }
        val ft = Text(falseText).apply {
            fill = Color.BLACK
            font = Font.loadFont(AppConfig.font, 30.0* multiple)
            rotate = 5.0
            effect = dropShadow
            setAlignment(this, Pos.BOTTOM_RIGHT)
        }
        val tt = Text(trueText).apply {
            fill = Color.WHITE
            font = Font.loadFont(AppConfig.font, 20.0* multiple)
            rotate = -10.0
            setAlignment(this, Pos.TOP_LEFT)
            setMargin(this, Insets(3.0* multiple, .0, .0, 5.0* multiple))
            isVisible = false
        }
        pane.children.addAll(AnchorPane(pick), tt, ft)
        pane.prefWidth = prefWidth
        pane.prefHeight = prefHeight
        enteredProperty.addListener { _, _, v ->
            if (v) {
                tt.isVisible = true
                pick.points.setAll(lines1)
            } else {
                tt.isVisible = false
                pick.points.setAll(lines)
            }
        }
        return pane
    }

}